﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace Dwarf.Managed
{
    class Settings
    {
        public string dwarfName;
        public string inputFile;
        public string resultsFile;
        public string profileFile;
        private int MaxItemWeight;
        private List<Item> Items;

        private static int maxArraySize = 5000;

        public void GetSettings(string[] args)
        {
            dwarfName = "Dwarf.DynamicProgramming";
            parseArguments(
                    args.Length,
                    args,
                    ref inputFile,
                    ref profileFile,
                    ref resultsFile);

            Items = ReadData(inputFile, out MaxItemWeight);

            WriteSettings();

        }

        public List<Item> GetItems() { return Items; }
        public int GetMaxCost() { return MaxItemWeight; }

        public Settings()
        {
            inputFile = new String(new char[maxArraySize]);
            resultsFile = new String(new char[maxArraySize]);
            profileFile = new String(new char[maxArraySize]);
        }

        public void WriteSettings()
        {
            Console.WriteLine("Kernel settings summary:");
            Console.WriteLine("Dwarf name       : " + dwarfName);
            Console.WriteLine("InputFile        : " + inputFile);
            Console.WriteLine("ResultsFile      : " + resultsFile);
            Console.WriteLine("ProfileFile      : " + profileFile);
            Console.WriteLine();
        }
        /// <summary>Parse the command line arguments and fill the reference parameters</summary>
        /// <param name="argc">Count of command line tokens</param>
        /// <param name="argv">Command line tokens</param>
        /// <param name="log">Settings log (debug/benchmark)</param>
        /// <param name="inputFile">Name of input text file</param>
        /// <param name="outputFile">Name of output file</param>
        [DllImport(@"CliTools.dll")]
        private static extern void parseArguments(
            int argc,
            String[] argv,
            ref string inputFile,
            ref string profileFile,
            ref string resultFile
            );

        [DllImport(@"CliTools.dll")]
        private static extern void usage();

        [DllImport(@"CliTools.dll")]
        public static extern void start();

        [DllImport(@"CliTools.dll")]
        public static extern void stop(ref double Time);

        /// <summary>Input of results</summary>
        ///
        public void Finish(double time, Solution[] Answers)
        {

            Console.WriteLine();
            Console.WriteLine("Clock time (sec): {0} ", time.ToString("F8"));

            using (StreamWriter outputResult = File.CreateText(resultsFile))
            {
                using (StreamWriter outputProfile = File.CreateText(profileFile))
                {
                    outputProfile.WriteLine("#Dwarfname:{0}", dwarfName);
                    outputProfile.WriteLine("#Time: {0}", DateTime.Now.ToString());
                    outputProfile.WriteLine("#Result time (sec): {0}", time.ToString("F8"));

                    //the actual results.
                    outputResult.WriteLine("The optimal solution for cost {0} is:", MaxItemWeight);
                    outputResult.WriteLine("Cost: {0}, Value: {1}", Answers[MaxItemWeight].Cost, Answers[MaxItemWeight].Value);
                    outputResult.WriteLine("With elements being:");
                    outputResult.Write(Answers[MaxItemWeight].ToString());

                    outputProfile.WriteLine("#eof");
                }
            }
        }

        /// <summary>
        /// Read the Item data, one Item value and associated cost per line, 
        /// into a list of Items.
        /// </summary>
        /// <remarks>
        /// The first line of the file contains a single integer representing
        /// the maximum allowed cost C.
        /// The second line contains a single integer representing the number of elements in the input file.
        /// Each subsequent line contains two integer values for a given item: 
        /// 1) item cost, and
        /// 2) item value.
        /// </remarks>
        /// <param name="filename">The name of the text file containing the Item data.</param>
        private List<Item> ReadData(string filename, out int MaximumCost)
        {
            int NumItems;
            StreamReader inFile = null;
            Items = new List<Item>();
            try
            {
                //Open the file.
                inFile = File.OpenText(filename);

                //Set the maximum cost for the solver.
                MaximumCost = int.Parse(inFile.ReadLine());

                //For each remaining line in the file:
                NumItems = int.Parse(inFile.ReadLine());

                string[] itemAttributes;

                //Use these characters to seperate the input.
                char[] delimiters = { ',', ' ' };

                for (int i = 0; i < NumItems; ++i)
                {
                    //Create a new item with the associated cost and value of the given line
                    //cost, value
                    itemAttributes = inFile.ReadLine().Split(delimiters, 2);
                    Items.Add(new Item(int.Parse(itemAttributes[0]), int.Parse(itemAttributes[1]), i));
                }
                //Close the file.
                inFile.Close();
            }
            catch (Exception e)
            {
                //If there is an error then print a useful message and terminate.
                Console.Out.WriteLine(e.Message);
                Console.Out.WriteLine(e.StackTrace);
                throw new Exception("Error in processing input file.");
            }
            return Items;
        }


    }
}
